/*
Kakine
ActionScript Framework
Copyright © 2011, PUNY, LLC.

This file is part of KAKINE.

KAKINE is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

KAKINE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with KAKINE.  If not, see <http://www.gnu.org/licenses/>.
*/ 
package com.puny.mvc.views.effect
{
	import com.puny.mvc.BaseObject;
	import com.puny.mvc.helpers.DelayHelper;
	
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.media.Sound;
	import flash.media.SoundChannel;
	import flash.media.SoundTransform;
	import flash.net.URLRequest;

	/**
	 * $Revision: 706 $
	 * SoundView class
	 */
	public class SoundView extends BaseObject
	{
		public static const DONE:String = "done";
		private static var _count:uint = 0;
		private var _check:Boolean = false;



		private static var _switch:Boolean = true;
		private static var _half:Number;
		
		private var _sound:flash.media.Sound;
		private var _channel:SoundChannel;
		private var _name:String;
//		private var _fixed:Boolean = true;
		private var _transform:SoundTransform = new SoundTransform();
		private var _callback:Function;
		private var _delay:int;
		private var _id:uint;
		private var _event:Event = new Event(DONE);
//		private var _filename:String;
		
		public static function count():uint {
			return _count;
		}
		
		/**
		 * Sound ON
		 */
		public static function soundON():void {
			trace("Sound ON");
			_switch = true;
		}
		
		/**
		 * Sound OFF
		 */
		public static function soundOFF():void {
			trace("Sound OFF");
			_switch = false;
		}
		
		public static function get state():Boolean {
			return _switch;
		}
		
		/**
		 * Constructor
		 * @param sound file name
		 */
		public function SoundView(filename:Object) {
			super(filename);
			trace("sound:", filename as String, _count++);
//			_filename = filename;
		}
		
		public function setCallback(fnc:Function, value:uint=0):void {
			_callback = fnc;
			_delay = value;
		}
		
		
		override public function afterOpen():void {
			super.afterOpen();
			_half = stage.stageWidth / 2;
		}
		
		/**
		 * load sound file
		 * @param sound file name
		 */
		final override protected function boot(filename:Object=null):void {
			if (filename==null) {
				loaded();
				return;
			} else if (filename is Sound) {
				_sound = filename as Sound;
				_name = _sound.url;
				loaded();
			} else if (filename is String) {
				_name = filename as String;
				_sound = new Sound();
				_sound.addEventListener(Event.COMPLETE, loaded, false, 0, true);
				_sound.addEventListener(IOErrorEvent.IO_ERROR, errorHandler, false, 0, true);
				var urlRequest:URLRequest = new URLRequest(_name);
				_sound.load(urlRequest);
			} else {
				super.boot(filename);
			}
		}
		
		private function errorHandler(event:IOErrorEvent):void {
			trace(event);
			//throw new Error(_filename);
		}
		
		/**
		 * Sound stops when this is removed.
		 */
		override public function afterClose():void {
			stop();
			if (_sound!=null) {
				_sound.removeEventListener(Event.COMPLETE, loaded);
				_sound.removeEventListener(IOErrorEvent.IO_ERROR, errorHandler);
			}
			if (_channel!=null) {
				_channel.removeEventListener(Event.SOUND_COMPLETE, loopHandler);
				_channel.removeEventListener(Event.SOUND_COMPLETE, closeHandler);
			}
			_sound = null;
			_channel = null;
			_transform = null;
			_callback = null;
			trace("sound close:", _name, _count++);
			_count--;
		}
		public function playPan(pos:Number,loop:Boolean=false):void {
				var pan:Number = pos / _half - 1;
				_transform.pan = pan < -1 ? -1 : (pan > 1) ? 1 : pan;
				play(loop);
		}
		/**
		 * start to play the sound file
		 * @param if true, play sound infinitely
		 */
		public function play(loop:Boolean=false):void {
			if (_switch&&_sound!=null&&_channel==null) {
				_channel = _sound.play(0,0,_transform);
				if (loop) {
					_channel.addEventListener(Event.SOUND_COMPLETE, loopHandler, false, 0, true);
				} else {
//					trace(_name, "starts");
					_channel.addEventListener(Event.SOUND_COMPLETE, closeHandler, false, 0, true);
					if (_callback!=null) {
						DelayHelper.setup(_delay,null,_callback);
					}
				}
			}
		}
		
		/**
		 * Stop the sound
		 */
		public function stop():void {
			if (_channel != null) {
				_channel.stop();
				closeHandler();
			}
		}

		private function loopHandler(event:Event):void {
			_channel.removeEventListener(Event.SOUND_COMPLETE, loopHandler);
			_channel = null;
			play(true);
		}
		
		private function closeHandler(event:Event=null):void {
			if (_channel != null) {
//				trace(_name, "stopped");
				_channel.removeEventListener(Event.SOUND_COMPLETE, loopHandler);
				_channel.removeEventListener(Event.SOUND_COMPLETE, closeHandler);
//				fixed = true;
			}
			dispatchEvent(_event.clone());
			_channel = null;
		}
		
//		private function adjustPan():void {
//			if (!fixed&&stage!=null) {
//				var pan:Number = localToGlobal(new Point(0,0)).x * 2 / stage.stageWidth - 1;
//				_transform.pan = pan < -1 ? -1 : (pan > 1) ? 1 : pan;
//				trace(_name, "pan="+_transform.pan);
//			}
//		}
//		private function panHandler():Boolean {
//			adjustPan();
//			if (_channel!=null) {
//				_channel.soundTransform = _transform;
//			}
//			return !fixed;
//		}
		
		/**
		 * volume: 0 to 1
		 */
		public function get volume():Number {
			return _transform.volume;
		}

		public function set volume(value:Number):void {
			_transform.volume = value;
//			trace(_name, "volume="+_transform.volume);
			if (_channel != null) {
				_transform.volume = value;
				_channel.soundTransform = _transform;
			}	
		}
		
	}
}